home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 41
/
Aminet 41 (2001)(Schatztruhe)[!][Feb 2001].iso
/
Aminet
/
comm
/
misc
/
ClipWatch.lha
/
ClipWatch
/
Sources
/
GraphClass.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-12-29
|
9KB
|
374 lines
/* GraphClass by Marc Le Douarain */
/* based on example by Stefan Stuntz */
/*
** This is the instance data for our custom class.
*/
struct GraphClassData
{
struct Str_AffiTraceGraph * GraphData;
};
#define SHOW_GRAPH 0x8022
void PrepCoeffForY(struct Str_AffiTraceGraph * Gfx,double ValMini,double ValMaxi,int YMini,int YMaxi)
{
double a,b;
a=(double)(YMaxi-YMini)/(double)(ValMaxi-ValMini);
b=YMini-(a*ValMini);
Gfx->CoeffAY=a;
Gfx->CoeffBY=b;
}
int ConvertYValueToPix(struct Str_AffiTraceGraph *Gfx,double Val)
{
int resY;
resY=(int)(Gfx->CoeffAY*Val+Gfx->CoeffBY);
return(resY);
}
void PrepCoeffForX(struct Str_AffiTraceGraph * Gfx,time_t ValMini,time_t ValMaxi,int XMini,int XMaxi)
{
double a,b;
a=(double)(XMaxi-XMini)/(double)(ValMaxi-ValMini);
b=XMini-(a*ValMini);
Gfx->CoeffAX=a;
Gfx->CoeffBX=b;
}
int ConvertXValueToPix(struct Str_AffiTraceGraph *Gfx,time_t Val)
{
int resX;
resX=(int)(Gfx->CoeffAX*Val+Gfx->CoeffBX);
return(resX);
}
void DrawDotted(struct RastPort * rp,int x_end,int y_end)
{
int i,x_start,y_start,xtaille,ytaille;
int steps;
double c_x,c_y;
x_start=rp->cp_x;
y_start=rp->cp_y;
ytaille=y_end-y_start;
xtaille=x_end-x_start;
if ( xtaille>=abs(ytaille) )
{
steps=xtaille;
c_x=1;
c_y=(double)(ytaille)/(double)steps;
}
else
{
steps=ytaille;
c_y=1;
c_x=(double)(xtaille)/(double)steps;
}
for(i=0;i<steps;i=i+3)
{
Move(rp,(int)(x_start+(double)i*c_x),(int)(y_start+(double)i*c_y));
Draw(rp,(int)(x_start+(double)i*c_x),(int)(y_start+(double)i*c_y));
}
}
time_t GetRound(time_t Val,time_t Pas)
{
time_t T;
T=Val/Pas;
return(T*Pas+Pas);
}
int DrawYScale(struct RastPort * rp,int PxLeft,int PxYMini,int PxYMaxi,double ValYMini,double ValYMaxi)
{
char tmp[50];
char tmp2[50];
int PxDateDeb;
int DecalagePix;
int DecalagePix2;
/* SetAPen(_rp(obj),_dri(obj)->dri_Pens[HIGHLIGHTTEXTPEN]);*/
sprintf(tmp,"%.4f",ValYMaxi);
sprintf(tmp2,"%.4f",ValYMini);
/* Length in pixels */
DecalagePix=TextLength(rp,tmp,strlen(tmp));
DecalagePix2=TextLength(rp,tmp2,strlen(tmp2));
if (DecalagePix2>DecalagePix)
DecalagePix=DecalagePix2;
/* Displaying mini and maxi values for Y */
Move(rp,PxLeft,PxYMaxi+2);
Text(rp,tmp,strlen(tmp));
Move(rp,PxLeft,PxYMini+4);
Text(rp,tmp2,strlen(tmp2));
PxDateDeb=PxLeft+DecalagePix+4;
/* Drawing Y Axe */
Move(rp,PxDateDeb,PxYMaxi);
Draw(rp,PxDateDeb,PxYMini+3);
return PxDateDeb;
}
void DrawXScale(struct RastPort * rp,struct Str_AffiTraceGraph *Gfx,int PxYMini,int PxDateDeb,int PxDateFin,time_t TpsDeb,time_t TpsFin)
{
time_t DiffTps;
time_t Tab[5][3]={{24*3600,3600,1},{2*24*3600,2*3600,1},{7*24*3600,24*3600,2},{31*24*3600,24*3600,3}};
time_t PasTps=0;
int AffiEchelleTps=0;
time_t TpsI;
int i;
/* SetAPen(_rp(obj),_dri(obj)->dri_Pens[HIGHLIGHTTEXTPEN]);*/
/* Scale */
Move(rp,PxDateDeb-3,PxYMini);
Draw(rp,PxDateFin,PxYMini);
/* Size of time */
DiffTps=TpsFin-TpsDeb;
PasTps=0;
for (i=0;i<=3;i++)
{
if(DiffTps==Tab[i][0])
{
PasTps=Tab[i][1];
AffiEchelleTps=Tab[i][2];
}
}
/* Graduation */
if (PasTps)
{
TpsI=GetRound(TpsDeb,PasTps);
do
{
int X;
char TmpD[20],TmpH[20],Grad[50];
X=ConvertXValueToPix(Gfx,TpsI);
Move(rp,X,PxYMini-2);
Draw(rp,X,PxYMini+2);
convert_long_to_asciidate(TpsI,TmpD,TmpH);
if (AffiEchelleTps==1)
{
if (TmpH[0]!='0')
{
Grad[0]=TmpH[0];
Grad[1]=TmpH[1];
Grad[2]='\0';
}
else
{
Grad[0]=TmpH[1];
Grad[1]='\0';
}
Move(rp,X-6,PxYMini+4+8);
Text(rp,Grad,strlen(Grad));
}
if (AffiEchelleTps==2)
{
Grad[0]=TmpD[0];
Grad[1]=TmpD[1];
Grad[2]=TmpD[2];
Grad[3]=TmpD[3];
Grad[4]=TmpD[4];
Grad[5]='\0';
Move(rp,X+10,PxYMini+4+8);
Text(rp,Grad,strlen(Grad));
}
if (AffiEchelleTps==3)
{
Grad[0]=TmpD[0];
Grad[1]=TmpD[1];
Grad[2]='\0';
Move(rp,X+2,PxYMini+4+8);
Text(rp,Grad,strlen(Grad));
}
TpsI=TpsI+PasTps;
}
while(TpsI<=TpsFin);
}
}
/*
** OM_SET method, we need to see if someone want to display a graph.
*/
SAVEDS ULONG mSet(struct IClass *cl,Object *obj,Msg msg)
{
struct GraphClassData *Data = INST_DATA(cl,obj);
struct TagItem *tags,*tag;
for (tags=((struct opSet *)msg)->ops_AttrList;tag=NextTagItem(&tags);)
{
switch (tag->ti_Tag)
{
case SHOW_GRAPH:
if (tag->ti_Data)
{
Data->GraphData = ((struct Str_AffiTraceGraph *)tag->ti_Data);
MUI_Redraw(obj,MADF_DRAWOBJECT); /* redraw ourselves completely */
}
break;
}
}
return(DoSuperMethodA(cl,obj,msg));
}
/*
** AskMinMax method will be called before the window is opened
** and before layout takes place. We need to tell MUI the
** minimum, maximum and default size of our object.
*/
SAVEDS ULONG mAskMinMax(struct IClass *cl,Object *obj,struct MUIP_AskMinMax *msg)
{
/*
** let our superclass first fill in what it thinks about sizes.
** this will e.g. add the size of frame and inner spacing.
*/
DoSuperMethodA(cl,obj,msg);
/*
** now add the values specific to our object. note that we
** indeed need to *add* these values, not just set them!
*/
msg->MinMaxInfo->MinWidth += 100;
msg->MinMaxInfo->DefWidth += 120;
msg->MinMaxInfo->MaxWidth += 1280;
msg->MinMaxInfo->MinHeight += 40;
msg->MinMaxInfo->DefHeight += 90;
msg->MinMaxInfo->MaxHeight += 800;
return(0);
}
/*
** Draw method is called whenever MUI feels we should render
** our object. This usually happens after layout is finished
** or when we need to refresh in a simplerefresh window.
** Note: You may only render within the rectangle
** _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj).
*/
SAVEDS ULONG mDraw(struct IClass *cl,Object *obj,struct MUIP_Draw *msg)
{
struct GraphClassData *Data = INST_DATA(cl,obj);
struct Str_AffiTraceGraph *Graph;
int i;
int PxLeft;
int PxDateDeb;
int PxDateFin;
int PxYMini;
int PxYMaxi;
double ValYMini=0;
double ValYMaxi=0;
PxLeft=_mleft(obj)+2;
PxDateDeb=_mleft(obj)+12;
PxDateFin=_mright(obj)-5;
PxYMini=_mbottom(obj)-18;
PxYMaxi=_mtop(obj)+5;
Graph=Data->GraphData;
/* Searching minis and maxis */
if (Graph)
{
if (Graph->NbrSamples>0)
{
ValYMini=Graph->Valeurs[0];
ValYMaxi=Graph->Valeurs[0];
for(i=1;i<Graph->NbrSamples;i++)
{
if (ValYMini>Graph->Valeurs[i])
ValYMini=Graph->Valeurs[i];
if (ValYMaxi<Graph->Valeurs[i])
ValYMaxi=Graph->Valeurs[i];
}
}
}
/*
** let our superclass draw itself first, area class would
** e.g. draw the frame and clear the whole region. What
** it does exactly depends on msg->flags.
*/
DoSuperMethodA(cl,obj,msg);
/*
** if MADF_DRAWOBJECT isn't set, we shouldn't draw anything.
** MUI just wanted to update the frame or something like that.
*/
if (!(msg->flags & MADF_DRAWOBJECT))
return(0);
/*
** ok, everything ready to render...
*/
if (Graph)
{
/* Drawing the scales */
SetAPen(_rp(obj),_dri(obj)->dri_Pens[HIGHLIGHTTEXTPEN]);
if(Graph->NbrSamples>0)
{
PrepCoeffForY(Graph,ValYMini,ValYMaxi,PxYMini,PxYMaxi);
PxDateDeb=DrawYScale(_rp(obj),PxLeft,PxYMini,PxYMaxi,ValYMini,ValYMaxi);
}
PrepCoeffForX(Graph,AffiGraphGene.Time32Deb,AffiGraphGene.Time32Fin,PxDateDeb,PxDateFin);
DrawXScale(_rp(obj),Graph,PxYMini,PxDateDeb,PxDateFin,AffiGraphGene.Time32Deb,AffiGraphGene.Time32Fin);
/* Drawing the samples */
if(Graph->NbrSamples>0)
{
int x,y;
SetAPen(_rp(obj),_dri(obj)->dri_Pens[TEXTPEN]);
// x=ConvertXValueToPix(TRUE,Graph->Horodates[0],AffiGraphGene.Time32Deb,AffiGraphGene.Time32Fin,PxDateDeb,PxDateFin);
// y=ConvertYValueToPix(TRUE,Graph->Valeurs[0],ValYMini,ValYMaxi,PxYMini,PxYMaxi);
x=ConvertXValueToPix(Graph,Graph->Horodates[0]);
y=ConvertYValueToPix(Graph,Graph->Valeurs[0]);
Move(_rp(obj),x,y);
for (i=1;i<Graph->NbrSamples;i++)
{
// x=ConvertXValueToPix(FALSE,Graph->Horodates[i],Graph->Horodates[0],Graph->Horodates[Graph->NbrSamples-1],PxDateDeb,PxDateFin);
// y=ConvertYValueToPix(FALSE,Graph->Valeurs[i],ValYMini,ValYMaxi,PxYMini,PxYMaxi);
x=ConvertXValueToPix(Graph,Graph->Horodates[i]);
y=ConvertYValueToPix(Graph,Graph->Valeurs[i]);
if ( (Graph->Horodates[i]-Graph->Horodates[i-1]) <= 60*60 )
Draw(_rp(obj),x,y);
else
DrawDotted(_rp(obj),x,y);
}
}
}
return(0);
}
/*
** Here comes the dispatcher for our custom class. We only need to
** care about MUIM_AskMinMax and MUIM_Draw in this simple case.
** Unknown/unused methods are passed to the superclass immediately.
*/
#ifdef __GNUC__
SAVEDS ASM ULONG MyDispatcher(REG(a0,struct IClass *cl),REG(a2,Object *obj),REG(a1,Msg msg))
#else
SAVEDS ASM ULONG MyDispatcher(REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) Msg msg)
#endif
{
switch (msg->MethodID)
{
case OM_SET : return(mSet (cl,obj,(APTR)msg));
case MUIM_AskMinMax : return(mAskMinMax(cl,obj,(APTR)msg));
case MUIM_Draw : return(mDraw (cl,obj,(APTR)msg));
}
return(DoSuperMethodA(cl,obj,msg));
}